package com.atguigu.gmall.cart.service.impl;

import com.atguigu.gmall.cart.service.CartService;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.common.util.DateUtil;
import com.atguigu.gmall.model.cart.CartInfo;
import com.atguigu.gmall.model.product.SkuInfo;
import com.atguigu.gmall.product.client.ProductFeignClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
public class CartServiceImpl implements CartService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private ProductFeignClient productFeignClient;

    /*
    1.  先判断这个商品在缓存中是否存在！
        true:
            数量相加
            选中状态
            更新时间
        false:
            直接添加到购物车
     */
    @Override
    public void addToCart(Long skuId, Integer skuNum, String userId) {
        //  购物车的key
        String cartKey = getCartKey(userId);
        //  hget key field;
        CartInfo cartInfoExist = (CartInfo) redisTemplate.opsForHash().get(cartKey, skuId.toString());
        //  判断
        if (cartInfoExist!=null){
            //  说明有这个商品; 每个商品最多购买200件
            Integer num =  cartInfoExist.getSkuNum()+skuNum>200?200:cartInfoExist.getSkuNum()+skuNum;
            cartInfoExist.setSkuNum(num);
            //  判断选中状态；如果未选中，则改为选中状态.
            if (cartInfoExist.getIsChecked().intValue()==0){
                cartInfoExist.setIsChecked(1);
            }
            //  修改当前的更新时间
            cartInfoExist.setUpdateTime(new Date());
            //  再赋值一下实时价格;
            cartInfoExist.setSkuPrice(productFeignClient.getSkuPrice(skuId));
            //  更新到缓存
            //  this.redisTemplate.opsForHash().put(cartKey,skuId.toString(),cartInfoExist);
        } else {
            //  获取skuInfo 对象
            SkuInfo skuInfo = this.productFeignClient.getSkuInfo(skuId);
            //  获取数据：
            cartInfoExist = new CartInfo();
            cartInfoExist.setSkuId(skuId);
            cartInfoExist.setUserId(userId);
            cartInfoExist.setSkuNum(skuNum);
            //  放入购物车时价格 - 是缓存的价格
            cartInfoExist.setCartPrice(skuInfo.getPrice());
            //  实时购物车价格
            cartInfoExist.setSkuPrice(this.productFeignClient.getSkuPrice(skuId));
            cartInfoExist.setSkuName(skuInfo.getSkuName());
            cartInfoExist.setImgUrl(skuInfo.getSkuDefaultImg());
            cartInfoExist.setCreateTime(new Date());
            cartInfoExist.setUpdateTime(new Date());
            //  将数据放入缓存。
            //  this.redisTemplate.opsForHash().put(cartKey,skuId.toString(),cartInfoExist);
        }
        //  将数据放入缓存。
        this.redisTemplate.opsForHash().put(cartKey,skuId.toString(),cartInfoExist);
        //  购物车过期时间是30天不? 根据每个用户的购买力度：
    }

    //  简单版：不带合并
    //    @Override
    //    public List<CartInfo> getCartList(String userId, String userTempId) {
    //        //  声明一个集合
    //        List<CartInfo> cartInfoList = new ArrayList<>();
    //        String cartKey ="";
    //        //  登录：
    //        if (!StringUtils.isEmpty(userId)){
    //            //  查看购物车列表先组成缓存的key
    //            cartKey = this.getCartKey(userId);
    //        }
    //        //  未登录：
    //        if (!StringUtils.isEmpty(userTempId)){
    //            //  查看购物车列表先组成缓存的key
    //            cartKey = this.getCartKey(userTempId);
    //        }
    //        //  hvals key 查看购物车列表;
    //        cartInfoList = this.redisTemplate.opsForHash().values(cartKey);
    //        //  查看购物车时是有顺序的; 按照修改时间进行排序 降序;
    //        //    int compare(T o1, T o2);
    //        cartInfoList.sort((cart1,cart2)->{
    //            return DateUtil.truncatedCompareTo(cart2.getUpdateTime(),cart1.getUpdateTime(), Calendar.SECOND);
    //        });
    //        return cartInfoList;
    //    }

    /**
     * 合并购物车
     * @param userId
     * @param userTempId
     * @return
     */
    @Override
    public List<CartInfo> getCartList(String userId, String userTempId) {
        //  创建一个临时购物车集合
        List<CartInfo> cartInfoNoLoginList = new ArrayList<>();
        //  判断临时用户Id 不为空
        if (!StringUtils.isEmpty(userTempId)){
            //  获取购物车的key
            String cartKey = this.getCartKey(userTempId);
            //  根据这个购物车的key 来获取到临时购物车集合
            cartInfoNoLoginList = this.redisTemplate.boundHashOps(cartKey).values();
        }
        //  没有登录，并且cartInfoNoLoginList 不为空！
        if (StringUtils.isEmpty(userId)){
            if (!CollectionUtils.isEmpty(cartInfoNoLoginList)){
                //  排序：
                cartInfoNoLoginList.sort((cart1,cart2)-> DateUtil.truncatedCompareTo(cart2.getUpdateTime(),cart1.getUpdateTime(),Calendar.SECOND));
            }
            //  返回临时购物车集合
            return cartInfoNoLoginList;
        }
        //  获取登录与合并之后的购物车数据集合
        List<CartInfo> allCartInfoList = new ArrayList<>();
        //  处理登录：
        if (!StringUtils.isEmpty(userId)){
            //  获取到登录的key
            String cartKey = this.getCartKey(userId);
            //  获取登录购物车集合
            //  第一种方式：
            //            List<CartInfo> cartInfoLoginList = this.redisTemplate.boundHashOps(cartKey).values();
            //            if (!CollectionUtils.isEmpty(cartInfoNoLoginList)) {
            //                //  双重for循环比较！
            //            }
            //  第二种方式： BoundHashOperations<H, HK, HV> hset key field value;
            BoundHashOperations<String,String,CartInfo> boundHashOperations = this.redisTemplate.boundHashOps(cartKey);
            //  boundHashOperations.get(field) = hget key field;
            //  boundHashOperations.put(field,value); = hset key field value;
            //  boundHashOperations.values(); = hvals key;
            //  判断未登录购物车集合
            if (!CollectionUtils.isEmpty(cartInfoNoLoginList)){
                //  循环遍历
                for (CartInfo cartInfoNoLogin : cartInfoNoLoginList) {
                    //  判断 boundHashOperations.get(cartInfoNoLogin.getSkuId().toString())!=null
                    //  17 18
                    if (boundHashOperations.hasKey(cartInfoNoLogin.getSkuId().toString())){
                        //  说明skuId 相同！
                        CartInfo cartInfoLogin = boundHashOperations.get(cartInfoNoLogin.getSkuId().toString());
                        //  判断不能超过200;
                        Integer numValue = cartInfoLogin.getSkuNum()+cartInfoNoLogin.getSkuNum()>200?200:cartInfoLogin.getSkuNum()+cartInfoNoLogin.getSkuNum();
                        cartInfoLogin.setSkuNum(numValue);
                        //  设置修改时间
                        cartInfoLogin.setUpdateTime(new Date());
                        //  默认选中; 查看购物项的最新价格
                        //  cartInfoLogin.setSkuPrice(this.productFeignClient.getSkuPrice(cartInfoNoLogin.getSkuId()));
                        if (cartInfoNoLogin.getIsChecked().intValue()==1){
                            //  处理数据库为未选中的！
                            if (cartInfoLogin.getIsChecked().intValue()==0){
                                cartInfoLogin.setIsChecked(1);
                            }
                        }
                        //  写入缓存
                        boundHashOperations.put(cartInfoNoLogin.getSkuId().toString(),cartInfoLogin);
                    } else {
                        //  只处理选中的商品
                        //                        if (cartInfoNoLogin.getIsChecked().intValue()==1){
                        //                            //  处理数据库为未选中的！
                        //                            cartInfoNoLogin.setUserId(userId);
                        //                            cartInfoNoLogin.setCreateTime(new Date());
                        //                            cartInfoNoLogin.setUpdateTime(new Date());
                        //                            boundHashOperations.put(cartInfoNoLogin.getSkuId().toString(),cartInfoNoLogin);
                        //                        }
                        //  skuId 不相同的数据 19
                        //  细节处理： 不管选中状态是几都存储到登录中.
                        cartInfoNoLogin.setUserId(userId);
                        cartInfoNoLogin.setCreateTime(new Date());
                        cartInfoNoLogin.setUpdateTime(new Date());
                        boundHashOperations.put(cartInfoNoLogin.getSkuId().toString(),cartInfoNoLogin);
                    }
                }
                //  合并完成之后，删除未登录购物车
                this.redisTemplate.delete(this.getCartKey(userTempId));
            }

            //  查询登录购物车：查询已经合并的购物车集合
            allCartInfoList = boundHashOperations.values();
            //  判断
            if (CollectionUtils.isEmpty(allCartInfoList)){
                return new ArrayList<>();
            }
            //  如果不为空，排序返回所有集合数据
            allCartInfoList.sort((cart1,cart2)-> DateUtil.truncatedCompareTo(cart2.getUpdateTime(),cart1.getUpdateTime(),Calendar.SECOND));
        }
        //  返回数据
        return allCartInfoList;
    }

    @Override
    public void checkCart(Long skuId, String userId, Integer isChecked) {
        //  获取购物车的key
        String cartKey = this.getCartKey(userId);
        //  hget key field;
        CartInfo cartInfo = (CartInfo) this.redisTemplate.opsForHash().get(cartKey, skuId.toString());
        if (cartInfo!=null){
            cartInfo.setIsChecked(isChecked);
        }
        //  修改完之后，写回缓存.
        this.redisTemplate.opsForHash().put(cartKey,skuId.toString(),cartInfo);

    }

    @Override
    public void allCheckCart(String userId, Integer isChecked) {
        //  先获取购物车的key
        String cartKey = this.getCartKey(userId);
        //  获取所有的购物车列表 hvals key;
        List<CartInfo> cartInfoList = this.redisTemplate.opsForHash().values(cartKey);
        //  循环遍历    第一种：
        //        for (CartInfo cartInfo : cartInfoList) {
        //            //  赋值
        //            cartInfo.setIsChecked(isChecked);
        //            //  写回去   hset key field value;
        //            this.redisTemplate.opsForHash().put(cartKey,cartInfo.getSkuId().toString(),cartInfo);
        //        }
        //  field value  第二种：
        //  HashMap<String, Object> map = new HashMap<>();
        //  hmset key map;
        //        for (CartInfo cartInfo : cartInfoList) {
        //            //  修改状态
        //            cartInfo.setIsChecked(isChecked);
        //            //  将修改的数据放入map
        //            map.put(cartInfo.getSkuId().toString(),cartInfo);
        //        }
        //        this.redisTemplate.opsForHash().putAll(cartKey,map);

        //  第三种：
        Map<String, CartInfo> cartInfoMap = cartInfoList.stream().map(cartInfo -> {
            cartInfo.setIsChecked(isChecked);
            return cartInfo;
        }).collect(Collectors.toMap(cartInfo -> cartInfo.getSkuId().toString(), cartInfo -> cartInfo));
        //  写回去！
        this.redisTemplate.opsForHash().putAll(cartKey,cartInfoMap);

    }

    @Override
    public void deleteCart(String userId, Long skuId) {
        //  先获取购物车的key
        String cartKey = this.getCartKey(userId);
        //  删除数据 hdel key field;
        this.redisTemplate.opsForHash().delete(cartKey,skuId.toString());
    }

    @Override
    public void clearCart(String userId) {
        //  删除数据 del key
        this.redisTemplate.delete(this.getCartKey(userId));
    }

    @Override
    public List<CartInfo> getCartCheckedList(String userId) {
        //  先获取到购物车的key
        String cartKey = this.getCartKey(userId);
        //  获取所有选中的商品 is_checked = 1;
        List<CartInfo> cartInfoList = this.redisTemplate.opsForHash().values(cartKey);
        //  遍历
        if (!CollectionUtils.isEmpty(cartInfoList)){
            //  filter 过滤：符合条件的留下
            List<CartInfo> cartInfoCheckedList = cartInfoList.stream().filter(cartInfo -> cartInfo.getIsChecked().intValue() == 1).collect(Collectors.toList());
            //  返回选中的商品
            return cartInfoCheckedList;
        }
        //  返回空
        return null;
    }

    private String getCartKey(String userId) {
        return RedisConst.USER_KEY_PREFIX+ userId +RedisConst.USER_CART_KEY_SUFFIX;
    }


    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(3, 5, 1, 7, 19, 4);
        list.sort((cart1,cart2)-> cart2-cart1);
        System.out.println(list);

    }
}
